package com.beyondsoft.sabg.edu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.beyondsoft.sabg.edu.model.db.StudentInfo;
import com.beyondsoft.sabg.edu.model.dto.StudentDTO;
import com.beyondsoft.sabg.edu.repository.StudentRepo;
import com.beyondsoft.sabg.edu.service.StudentService;
import org.apache.commons.compress.utils.Lists;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author Mo cr
 * @Date 2023/8/18
 */
@Service
public class StudentServiceImplAbstract extends AbstractExportServiceImpl<StudentInfo, StudentDTO, StudentRepo>
        implements StudentService {
    private final Map<String, String> beanMapper = new HashMap(10);

    @PostConstruct
    public void postConstruct() {
        beanMapper.put("studentNumber", "学号");
        beanMapper.put("studentName", "姓名");
        beanMapper.put("studentEducation", "学历");
        beanMapper.put("studentStudyType", "学习方式");
        beanMapper.put("studentNation", "民族");
        beanMapper.put("studentPoliticalFace", "政治面貌");
        beanMapper.put("studentInSchool", "是否在校");
        beanMapper.put("studentCollege", "学院");
        beanMapper.put("studentProfession", "专业");
        beanMapper.put("studentGender", "性别");
    }

    @Override
    protected void addConditions(Root<StudentInfo> root, CriteriaBuilder criteriaBuilder, List<Predicate> predicates, Object o) {
        super.addConditions(root, criteriaBuilder, predicates, o);
        if (o instanceof StudentDTO) {
            StudentDTO studentDTO = (StudentDTO) o;
            if (StrUtil.isNotEmpty(studentDTO.getStudentNumber())) {
                predicates.add(criteriaBuilder.like(root.get("studentNumber"), "%" + studentDTO.getStudentNumber() + "%"));
            }
            if (studentDTO.getUserId() != null) {
                predicates.add(criteriaBuilder.equal(root.get("userAccount"), studentDTO.getUserId()));
            }
            if (studentDTO.getStudentEducation() != null) {
                predicates.add(criteriaBuilder.equal(root.get("studentEducation"), studentDTO.getStudentEducation()));
            }

            if (studentDTO.getStudentStudyType() != null) {
                predicates.add(criteriaBuilder.equal(root.get("studentStudyType"), studentDTO.getStudentStudyType()));
            }

            if (studentDTO.getStudentCollege() != null) {
                predicates.add(criteriaBuilder.like(root.get("studentCollege"), "%" + studentDTO.getStudentCollege() + "%"));
            }

            if (StrUtil.isNotEmpty(studentDTO.getStudentName())) {
                predicates.add(criteriaBuilder.like(root.get("studentName"), "%" + studentDTO.getStudentName() + "%"));
            }
            if (StrUtil.isNotEmpty(studentDTO.getStudentPoliticalFace())) {
                predicates.add(criteriaBuilder.like(root.get("studentPoliticalFace"), "%" + studentDTO.getStudentPoliticalFace() + "%"));
            }
            if (StrUtil.isNotEmpty(studentDTO.getStudentNation())) {
                predicates.add(criteriaBuilder.like(root.get("studentNation"), "%" + studentDTO.getStudentNation() + "%"));
            }
            if (StrUtil.isNotEmpty(studentDTO.getStudentInSchool())) {
                predicates.add(criteriaBuilder.equal(root.get("studentInSchool"), studentDTO.getStudentInSchool()));
            }

            if (StrUtil.isNotEmpty(studentDTO.getStudentProfession())) {
                predicates.add(criteriaBuilder.like(root.get("studentProfession"), "%" + studentDTO.getStudentProfession() + "%"));
            }
            if(studentDTO.getOnlyTag()!=null && studentDTO.getOnlyTag()){
                predicates.add((criteriaBuilder.notEqual(root.get("tag"), "")));
                predicates.add(criteriaBuilder.isNotNull(root.get("tag")));
            }

        }
    }

    @Override
    protected void saveBeforeProcess(Object o, StudentInfo studentInfo) {
        StudentDTO studentDTO = (StudentDTO) o;
        if (studentDTO.getId() != null) {

            Optional<StudentInfo> studentInfoOptional = getRepo().findById(studentDTO.getId());
            if (studentInfoOptional.isPresent()) {
                BeanUtil.copyProperties(studentInfoOptional.get(), studentInfo);
            }
        }
        studentDTO.setValidity(true);
        BeanUtil.copyProperties(studentDTO, studentInfo, "id");
    }


    @Override
    protected List<StudentInfo> getExportList(StudentDTO dto) {
        return (List<StudentInfo>) this.findAll(dto, Pageable.unpaged()).getData();
    }

    @Override
    protected Map getBeanMapper() {
        return beanMapper;
    }

    @Override
    public StudentDTO findOneByStudentNumber(String studentNumber) {
        return findAllByStudentNumber(List.of(studentNumber)).get(0);
    }

    @Override
    public List<StudentDTO> findAllByStudentNumber(List<String> studentNumbers) {
        if (CollUtil.isEmpty(studentNumbers)) {
            return new ArrayList<>();
        }
        return getRepo().findByStudentNumberIn(studentNumbers.stream()
                        .filter(StrUtil::isNotBlank)
                        .collect(Collectors.toList())
                ).stream()
                .map(studentInfo -> {
                    StudentDTO studentDTO = new StudentDTO();
                    studentDTO.setStudentNumber(studentInfo.getStudentNumber());
                    studentDTO.setStudentName(studentInfo.getStudentName());
                    studentDTO.setStudentGender(studentInfo.getStudentGender());
                    studentDTO.setStudentCollege(studentInfo.getStudentCollege());
                    studentDTO.setStudentProfession(studentInfo.getStudentProfession());
                    studentDTO.setStudentEducation(studentInfo.getStudentEducation());
                    studentDTO.setStudentGrade(studentInfo.getStudentGrade());
                    return studentDTO;
                }).collect(Collectors.toList());
    }
}
